/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
// PhantomExec.cpp : Defines the entry point for the console application.
//

// Enable these for memory stuff
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <direct.h>

#include "ScriptDLL.h"
#include "WindowsFunctions.h"
#include "SSI_LibraryManager.h"

#include "GlobalFuncs.h"

//#define __USE_LEAK_DETECT__
//#ifdef __USE_LEAK_DETECT__
//#include "C:\Projects\3rdPartyTools\TestMemLeakConsoleApp\MemCheckLib\MemLeakDetect.h"
//CMemLeakDetect aDetect;
//#endif

//#include "..\StdFuncs\StandardFunctions.h"

int LoadDLLs(CEngine* theEngine, const char* ExternalFile);

int main(int argc, char* argv[])
{


	//44-148
	//_CrtSetBreakAlloc(157);
	//_CrtSetBreakAlloc(120);
	//_CrtSetBreakAlloc(100);
	//_CrtSetBreakAlloc(60);
	//_CrtSetBreakAlloc(58);

	int ctr;

	String FileName;
	String RedirName;
	String Temp;


  SSI_BOOL doFile = 0;
	SSI_BOOL doDEBUG = 0;
	SSI_BOOL bREDIRECT = 0;

  int iLoopCount = 1;
  int iHaveFile = 0;
  int iHaveArgs = 0;
  String Args = "";


  // Change working directory so can get externals
  String sDir = argv[0];
  int iPos = sDir.ReverseFind("\\");
  if(iPos > 0){
    sDir = sDir.SubString(0, iPos - 1);
    chdir(sDir.Str());
  }

	for(ctr = 1; ctr < argc; ctr++){
    Temp = argv[ctr];
		if(Temp == "-d"){
			doDEBUG = 1;
		}else if(Temp == "-?"){
			printf("Usage:\n");
			printf("  phantom.exe [script] [-l count] [-o file] [-d] [script_args]\n\n");
			printf("   [script]      - The Phantom script to run [optional]\n");
			printf("   [-l count]    - Run the script 'count' times [optional]\n");
			printf("   [-o file]     - Capture all output to 'file' [optional]\n");
			printf("   [-d]          - Enter debug mode (enter 'help' in debug mode\n");
			printf("                   for commands).  Requires [script]. [optional]\n");
			printf("   [-?]          - Display this help message. [optional]\n");
			printf("   [script_args] - Additional arguments to pass to the script [optional]\n\n");
			printf("  Entering no arguments will start Phantom in console mode.\n");
			return 0;
		}else if (Temp == "-o"){
			ctr++;
			if(ctr > argc){
				printf("Expect output file name (-o).\n");
				return 0;
			}
			RedirName = argv[ctr];
			bREDIRECT = 1;
		}else if (Temp == "-l"){
			ctr++;
			if(ctr > argc){
				printf("Expect loop count (-l).\n");
				return 0;
			}
      if(sscanf(argv[ctr], "%d", &iLoopCount) != 1){
        printf("Expect integer loop count >= 0 (-l).\n");
        return 0;
      }
      if(iLoopCount < 0){
        printf("Expect integer loop count >= 0 (-l).\n");
        return 0;
      }
    }else if(iHaveFile == 0){
			FileName = argv[ctr];
			doFile = 1;
      iHaveFile = 1;
    }else{
      Args = Args + " ";
      Args = Args + argv[ctr];
      iHaveArgs = 1;
    }
	}

  if(FileName.GetLength() > 0){
	  printf("FileName is: %s\n", FileName.Str());
  }
  if(iHaveArgs){
    printf("Arguments: %s\n", Args.Str());
  }
  printf("    -----------------------------------------\n");
  printf("    | Phantom v2.1                          |\n");
  printf("    | http://www.phantomtest.com            |\n");
  printf("    | This DOS version is freeware          |\n");
  printf("    | Type 'stop' to quit.                  |\n");
  printf("    -----------------------------------------\n");
  
  if(doFile)
  {
		ssi_stream* instream;
		ssi_stream* outstream;

    while(iLoopCount > 0){
      std_stream astream;
    	std_ofile_stream ostream;
	    CLibraryManager LibMgr;

      iLoopCount--;
		  if(bREDIRECT){
			  CStatus aStat;
			  aStat = ostream.Open(RedirName, String("w"));
			  if(!aStat){
				  printf("%s\n", aStat.GetStatusMessage().Str());
				  return 0;
			  }
			  instream = &astream;
			  outstream = &ostream;
		  }else{
			  instream = &astream;
			  outstream = &astream;

			  SSI_INT64 dPos = FileName.ReverseFind(".");
			  String OutName = FileName.SubString(0,dPos-1);
			  OutName = OutName + ".log";
			  astream.SetOutFile(OutName.Str());
		  }
		  CScript aScript(instream, outstream);

      if(!aScript.Load(FileName)){
        printf("Could not open file: %s\n", FileName.Str());
        return 0;
      }

      /*
      String sLog = FileName;
      String Ret;
      sLog.Reverse();
      int iPos = sLog.Parse(".", Ret);
      sLog.Reverse();
      sLog = sLog + ".log";
      aScript.SetLog(sLog);
      */

		  LibMgr.LoadDLLs(aScript.Engine, "Externals.dat");

      if(iHaveArgs){
        if(!aScript.EvaluateArguments(Args)){
          if(bREDIRECT){
    			  ostream.Close();
		        Factory_ClearData();
		        LibMgr.FreeDLLs(aScript.Engine);
            return 0;
		      }
        }
      }

		  //LoadDLLs(aScript.Engine, "Externals.dat");
		  if(doDEBUG){
			  aScript.Run(DEBUG_MODE);
		  }else{
			  aScript.Run(NORMAL_MODE);
		  }
		  Factory_ClearData();
		  LibMgr.FreeDLLs(aScript.Engine);

		  if(bREDIRECT){
			  ostream.Close();
		  }
    }
  }
  else
  {
    std_stream astream;
  	std_ofile_stream ostream;
	  CLibraryManager LibMgr;

    CConsole aConsole(&astream, &astream);
		LibMgr.LoadDLLs(aConsole.Engine, "Externals.dat");

    //String s = aConsole.Engine->GetVariableTypes(String(";"));
    //s = aConsole.Engine->GetPackageContents(String("%"), String(":"));
    //printf("%s\n", s.Str());

    aConsole.Loop();
		Factory_ClearData();
		LibMgr.FreeDLLs(aConsole.Engine);
  }

	//_CrtDumpMemoryLeaks();  // Keeping in in debug mode slows things down!
  return 0;
}

int LoadDLLs(CEngine* theEngine, const char* ExternalFile){
	File aFile;
	String aStr;

	if(!aFile.Open(ExternalFile, "r")){
		printf("Warning: %s (external DLL list) not found\n", ExternalFile);
		//String s;
		//s.Format("Warning: %s (external DLL list) not found", ExternalFile);
		//theEngine->GetOutStream()->Disp(s.Str(), 1);
		return 0;
	}

	while(aFile.ReadLine(aStr) >= 0){

		theEngine->SetPackageName(aStr.Str());
		LoadDLL(aStr.Str(), theEngine);
	}

	return 1;

}